from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
from django.utils import timezone
from .models import Exam, ExamAttempt, Question, QuestionResponse
import json


def index(request):
    return render(request, "olexam/example_1.html")


@login_required
def exam_list(request):
    """显示可用的考试列表"""
    exams = Exam.objects.filter(status='published').order_by('-start_time')
    now = timezone.now()

    for exam in exams:
        exam.user_attempt = exam.attempts.filter(user=request.user).first()

    return render(request, 'olexam/exam_list.html', {
        'exams': exams,
        'now': now
    })

@login_required
def take_exam(request, exam_id):
    """参加考试视图"""
    exam = get_object_or_404(Exam, id=exam_id, status='published')
    now = timezone.now()

    # 检查考试时间
    if now < exam.start_time:
        return render(request, 'olexam/error.html', {
            'message': '考试尚未开始'
        })
    if now > exam.end_time:
        return render(request, 'olexam/error.html', {
            'message': '考试已结束'
        })

    # 获取或创建考试尝试
    attempt, created = ExamAttempt.objects.get_or_create(
        exam=exam,
        user=request.user,
        defaults={
            'start_time': now,
            'ip_address': request.META.get('REMOTE_ADDR')
        }
    )

    if attempt.status != 'in_progress':
        return render(request, 'olexam/error.html', {
            'message': '您已经完成本次考试'
        })

    # 处理表单提交
    if request.method == 'POST':
        for question in exam.questions.all():
            field_name = f"question_{question.id}"
            if field_name in request.POST:
                response_data = request.POST[field_name]

                # 对于多选题，需要特殊处理
                if question.type == 'multiple_choice':
                    response_data = request.POST.getlist(field_name)

                # 创建或更新回答
                response, _ = QuestionResponse.objects.update_or_create(
                    attempt=attempt,
                    question=question,
                    defaults={
                        'response': json.dumps(response_data),
                        'graded_by': None if question.type == 'programming' else request.user
                    }
                )

                # 自动评分非编程题
                if question.type != 'programming':
                    response.score = grade_response(question, response_data)
                    response.save()

        # 检查是否提交考试
        if 'submit_exam' in request.POST:
            attempt.submit_time = timezone.now()
            attempt.status = 'submitted'
            attempt.calculate_score()
            attempt.save()
            return redirect('exam_result', attempt_id=attempt.id)

    # 计算剩余时间
    remaining_time = exam.time_remaining(request.user)

    return render(request, 'olexam/take_exam.html', {
        'exam': exam,
        'attempt': attempt,
        'remaining_time': remaining_time,
        'responses': get_responses_dict(attempt)
    })

def grade_response(question, response_data):
    """评分函数"""
    question_type = question.get_question_type()

    if question.type == 'true_false':
        return question.score if str(response_data).lower() == str(question_type.correct_answer).lower() else 0

    elif question.type == 'single_choice':
        try:
            return question.score if int(response_data) == question_type.correct_option else 0
        except (ValueError, TypeError):
            return 0

    elif question.type == 'multiple_choice':
        try:
            # 将响应转换为整数集合
            response_set = set(int(x) for x in response_data)
            correct_set = set(json.loads(question_type.correct_options))

            # 全对才得分
            return question.score if response_set == correct_set else 0
        except (ValueError, TypeError):
            return 0

    return 0

def get_responses_dict(attempt):
    """获取用户回答的字典形式"""
    return {r.question_id: json.loads(r.response) for r in attempt.responses.all()}

@login_required
def exam_result(request, attempt_id):
    """考试结果视图"""
    attempt = get_object_or_404(ExamAttempt, id=attempt_id, user=request.user)
    responses = attempt.responses.select_related('question').all()

    # 为每个回答添加问题类型实例
    for response in responses:
        response.question_type = response.question.get_question_type()
        response.response_data = json.loads(response.response)

    return render(request, 'olexam/exam_result.html', {
        'attempt': attempt,
        'responses': responses,
        'exam': attempt.exam
    })
